package com.gpj.flowable.core.tools;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @className JsonUtils
 * @description json操作工具类
 * @author GPJ
 * @date 2023/11/11 22:13
 * @version 1.0
 **/
@Slf4j
public class JsonUtils {
	private static final ObjectMapper mapper = new ObjectMapper()
			.findAndRegisterModules()
			.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

	public static String toJson(Object obj) {
		return handle(() -> mapper.writeValueAsString(obj));
	}

	public static byte[] toJsonB(Object obj) {
		return handle(() -> mapper.writeValueAsBytes(obj));
	}

	public static <T> T toObject(String context, Class<T> clazz) {
		return handle(() -> mapper.readValue(context, clazz));
	}

	public static <T> T toObject(byte[] bytes, Class<T> clazz) {
		return handle(() -> mapper.readValue(bytes, clazz));
	}

	public static <T> List<T> toList(byte[] bytes, Class<T> clazz) {
		JavaType javaType = mapper.getTypeFactory().constructCollectionType(List.class, clazz);
		return handle(() -> mapper.readValue(bytes, javaType));
	}

	public static <T> List<T> toList(String context, Class<T> clazz) {
		return handle(() -> mapper.readValue(context, mapper.getTypeFactory().constructCollectionType(List.class, clazz)));
	}

	public static JsonNode toJsonNode(String context){
		return handle(() -> mapper.readTree(context));
	}

	/*public static <K, V> Map<K, V> toMap(byte[] bytes, Class<K> keyClazz, Class<V> valueClazz) {
		return handle(() -> mapper.readValue(bytes, mapper.getTypeFactory().constructMapType(Map.class, keyClazz, valueClazz)));
	}

	public static <K, V> Map<K, V> toMap(String context, Class<K> keyClazz, Class<V> valueClazz) {
		return handle(() -> mapper.readValue(context, mapper.getTypeFactory().constructMapType(Map.class, keyClazz, valueClazz)));
	}*/

	private static <T> T handle(SupplierWithException<T> supplier){
		try {
			return supplier.get();
		}catch (Exception e) {
			log.error("json序列化失败:{}", e.getLocalizedMessage() ,e);
			return null;
		}
	}

	@FunctionalInterface
	interface SupplierWithException<T> {
		T get() throws Exception;
	}
}
